home *** CD-ROM | disk | FTP | other *** search
/ The Very Best of Atari Inside / The Very Best of Atari Inside 1.iso / mint / mntlib25 / _divdf3.cpp < prev    next >
C/C++ Source or Header  |  1992-12-12  |  5KB  |  213 lines

  1. |
  2. | double floating point divide routine
  3. |
  4. #ifndef __M68881__
  5.     .text
  6.     .even
  7.     .globl    __divdf3, ___divdf3
  8. #ifdef    ERROR_CHECK
  9. #include "errbase.h"
  10.     .globl    __infinitydf
  11. LC0:
  12.     .ascii "floating point division by 0\12\15\0"
  13.     .even
  14. #endif    ERROR_CHECK
  15.  
  16. __divdf3:
  17. ___divdf3:
  18. #ifdef    ERROR_CHECK
  19.     tstl    a7@(12)            | check if divisor is 0
  20.     bne    continue
  21.     tstl    a7@(16)
  22.     bne    continue
  23.  
  24.     pea    pc@(LC0)
  25.     pea    Stderr
  26.     jbsr    _fprintf    |
  27.     addql    #8,a7        |
  28.                     | set _errno to ERANGE
  29.     moveq    #ERANGE,d0
  30.     Emove    d0,Errno
  31.     moveml    __infinitydf,d0-d1    | return signed infinity 
  32.     btst    #31,a7@(4)        | transfer sign of dividend
  33.     beq    clear            | (mjr++)
  34.     bset    #31,d0            |
  35.     rts                |
  36. clear:                    |
  37.     bclr    #31,d0            |
  38.     rts
  39. continue:
  40.  
  41. #endif    /* ERROR_CHECK */
  42. #ifndef sfp004
  43. |
  44. | written by Kai-Uwe Bloem (I5110401@dbstu1.bitnet).
  45. | Based on a 80x86 floating point packet from comp.os.minix, written by P.Housel
  46. |
  47. | patched by Olaf Flebbe (flebbe@tat.physik.uni-tuebingen.de)
  48. |
  49. | Revision 1.2.1 olaf 11-92
  50. |   + prevent the tie rounding case if dividing is not exact.
  51. |      > paranoia now says: "Division appears to round correctly"
  52. |      ** requires _normdf Version 1.6.1 or later
  53. |
  54. |
  55. | Revision 1.2, kub 01-90 :
  56. | added support for denormalized numbers
  57. |
  58. | Revision 1.1, kub 12-89 :
  59. | Ported over to 68k assembler
  60. |
  61. | Revision 1.0:
  62. | original 8088 code from P.S.Housel
  63.  
  64. BIAS8    =    0x3FF-1
  65.  
  66.     lea    sp@(4),a0    | pointer to parameters u and v
  67.     moveml    d2-d7,sp@-    | save registers
  68.     moveml    a0@,d4-d5/d6-d7    | d4-d5 = u, d6-d7 = v
  69.  
  70.     movel    d4,d0        | d0 = u.exp
  71.     swap    d0
  72.     movew    d0,d2        | d2 = u.sign
  73.     lsrw    #4,d0
  74.     andw    #0x07ff,d0    | kill sign bit
  75.  
  76.     movel    d6,d1        | d1 = v.exp
  77.     swap    d1
  78.     eorw    d1,d2        | d2 = u.sign ^ v.sign (in bit 31)
  79.     lsrw    #4,d1
  80.     andw    #0x07ff,d1    | kill sign bit
  81.  
  82.     andl    #0x0fffff,d4    | remove exponent from u.mantissa
  83.     tstw    d0        | check for zero exponent - no leading "1"
  84.     beq    0f
  85.     orl    #0x100000,d4    | restore implied leading "1"
  86.     bra    1f
  87. 0:    addw    #1,d0        | "normalize" exponent
  88. 1:    movel    d4,d3
  89.     orl    d5,d3
  90.     beq    retz        | dividing zero
  91.  
  92.     andl    #0x0fffff,d6    | remove exponent from v.mantissa
  93.     tstw    d1        | check for zero exponent - no leading "1"
  94.     beq    0f
  95.     orl    #0x100000,d6    | restore implied leading "1"
  96.     bra    1f
  97. 0:    addw    #1,d1        | "normalize" exponent
  98. 1:    movel    d6,d3
  99.     orl    d7,d3
  100.  
  101. #ifndef    ERROR_CHECK
  102.     beq    divz        | divide by zero
  103. #endif    ERROR_CHECK
  104.  
  105.     movew    d2,a0        | save sign
  106.  
  107.     subw    d1,d0        | subtract exponents,
  108.     addw    #BIAS8-11+1,d0    |  add bias back in, account for shift
  109.     addw    #66,d0        |  add loop offset, +2 for extra rounding bits
  110.                 |   for denormalized numbers (2 implied by dbra)
  111.     movew    #24,d1        | bit number for "implied" pos (+4 for rounding)
  112.     movel    #-1,d2        | zero the quotient
  113.     movel    #-1,d3        |  (for speed it is a one''s complement)
  114.     subl    d7,d5        | initial subtraction,
  115.     subxl    d6,d4        | u = u - v
  116. 2:
  117.     btst    d1,d2        | divide until 1 in implied position
  118.     beq    5f
  119.  
  120.     addl    d5,d5
  121.     addxl    d4,d4
  122.     bcs    4f        | if carry is set, add, else subtract
  123.  
  124.     addxl    d3,d3        | shift quotient and set bit zero
  125.     addxl    d2,d2
  126.     subl    d7,d5        | subtract
  127.     subxl    d6,d4        | u = u - v
  128.     dbra    d0,2b        | give up if result is denormalized
  129.     bra    5f
  130. 4:
  131.     addxl    d3,d3        | shift quotient and clear bit zero
  132.     addxl    d2,d2
  133.     addl    d7,d5        | add (restore)
  134.     addxl    d6,d4        | u = u + v
  135.     dbra    d0,2b        | give up if result is denormalized
  136. 5:    subw    #2,d0        | remove rounding offset for denormalized nums
  137.     notl    d2        | invert quotient to get it right
  138.     notl    d3
  139.  
  140.     movel   d5,d1
  141.     orl     d4,d1           | check for exact result
  142.     beq     1f              
  143.     moveql  #-1,d1          | Set rounding bits for tie case
  144. 1:    movel    d2,d4        | save quotient mantissa
  145.     movel    d3,d5
  146.     movew    a0,d2        | get sign back
  147.     jmp    norm_df        | (registers on stack removed by norm_df)
  148.  
  149. retz:    clrl    d0        | zero destination
  150.     clrl    d1
  151.     moveml    sp@+,d2-d7
  152.     rts            | no normalization needed
  153.  
  154. #ifndef    ERROR_CHECK
  155. | NOTE: __infinitydf is in the text segment
  156. divz: moveml  __infinitydf,d0-d1 | return infinity value
  157.     moveml    sp@+,d2-d7    | should really cause trap ?!?
  158.  
  159.     btst    #31,a7@(4)        | transfer sign of dividend
  160.     beq    clear            | (mjr++)
  161.     bset    #31,d0            |
  162.     rts                |
  163. clear:                    |
  164.     bclr    #31,d0            |
  165.     rts
  166.  
  167. #endif    ERROR_CHECK
  168.  
  169. #else
  170.  
  171. | double precision floating point stuff for Atari-gcc using the SFP004
  172. | developed with gas
  173. |
  174. | double precision division
  175. |
  176. | M. Ritzert (mjr at dmzrzu71)
  177. |
  178. | 4.10.1990
  179. |
  180. | no NAN checking implemented to gain compatibility with the TT-lib
  181. |
  182. | addresses of the 68881 data port. This choice is fastest when much data is
  183. | transferred between the two processors.
  184.  
  185. comm =     -6
  186. resp =    -16
  187. zahl =      0
  188.  
  189. | waiting loop ...
  190. |
  191. | wait:
  192. | ww:    cmpiw    #0x8900,a0@(resp)
  193. |     beq    ww
  194. | is coded directly by
  195. |    .long    0x0c688900, 0xfff067f8
  196.  
  197.     lea    0xfffffa50:w,a0
  198.     movew    #0x5400,a0@(comm)    | load first argument to fp0
  199.     cmpiw    #0x8900,a0@(resp)    | check
  200.     movel    a7@(4),a0@
  201.     movel    a7@(8),a0@
  202.     movew    #0x5420,a0@(comm)
  203.     .long    0x0c688900, 0xfff067f8
  204.     movel    a7@(12),a0@
  205.     movel    a7@(16),a0@
  206.     movew    #0x7400,a0@(comm)    | result to d0
  207.     .long    0x0c688900, 0xfff067f8
  208.     movel    a0@,d0
  209.     movel    a0@,d1
  210.      rts
  211. #endif    sfp004
  212. #endif /* !__M68881__ */
  213.